#include "EventLoop.h"
#include <sys/eventfd.h>
EventLoop::EventLoop(Acceptor &acceptor)
    : _epfd(createEpollFd()), _eventfd(createEventfd()), _acceptor(acceptor), _isLooping(false), _evArr(1000)
{
    addEpollReadEvent(_acceptor.fd());
    addEpollReadEvent(_eventfd);
}
EventLoop::~EventLoop(){
    close(_epfd);
    close(_eventfd);
}
int EventLoop::createEpollFd()
{
    int epfd = epoll_create1(0);
    if (epfd < 0)
    {
        perror("epoll_create1");
    }
    return epfd;
}
int EventLoop::createEventfd()
{
    int eventfd = ::eventfd(0, 0);
    if (eventfd < 0)
    {
        perror("eventfd");
    }
    return eventfd;
}
void EventLoop::addEpollReadEvent(int fd)
{
    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.data.fd = fd;
    ev.events = EPOLLIN;
    int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &ev);
    if (ret < 0)
    {
        perror("epoll_ctl");
    }
}
void EventLoop::delEpollReadEvent(int fd)
{
    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.data.fd = fd;
    ev.events = EPOLLIN;
    int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, &ev);
    if (ret < 0)
    {
        perror("epoll_ctl");
    }
}
void EventLoop::loop()
{
    _isLooping = true;
    while (_isLooping)
    {
        waitEpollFd();
    }
}
void EventLoop::unloop()
{
    _isLooping = false;
}
void EventLoop::waitEpollFd()
{
    int nready = epoll_wait(_epfd, _evArr.data(), _evArr.size(), 5000);
    if (nready == -1 && errno == EINTR)
    {
        return;
    }
    else if (nready == -1)
    {
        perror("epoll_wait");
        exit(EXIT_FAILURE);
    }
    else if (nready == 0)
    {
        printf("epoll timeout\n");
    }
    else
    {
        for (int i = 0; i < nready; ++i)
        {
            int fd = _evArr[i].data.fd;
            if (fd == _acceptor.fd())
            {
                printf("有新连接进入\n");
                handleNewConnection();
            }
            else if (fd == _eventfd)
            {
                handleReadEvent();
                doPendingFunctors();
            }
            else
            {
                handleNewMessage(fd);
            }
        }
    }
}

void EventLoop::handleNewConnection()
{
    int netfd = _acceptor.accept();
    addEpollReadEvent(netfd);
    // 创建新连接对象
    TcpConnectionPtr conn(new TcpConnection(netfd, this));
    conn->setAllCallback(_onConnection, _onMessage, _onClose);
    _conns.insert({netfd, conn});
    conn->handlenewConnectionCallback();
}
void EventLoop::handleNewMessage(int fd)
{
    auto it = _conns.find(fd);
    bool isClosed = it->second->isClosed();
    if (isClosed)
    {
        it->second->handleCloseCallback();
        delEpollReadEvent(fd);
        _conns.erase(fd);
    }
    else
    {
        it->second->handleMessageCallback();
    }
}
void EventLoop::doPendingFunctors()
{
    printf("dopendingFunctors\n");
    vector<Functor> tmp;
    {
        MutexLockGuard autolock(_mutex);
        tmp.swap(_pendingFunctors);
    }
    for (auto &fun : tmp)
    {
        fun();
    }
}
void EventLoop::setAllCallbacks(Callback &&cb1,Callback &&cb2,Callback &&cb3){
    _onConnection = std::move(cb1);
    _onMessage = std::move(cb2);
    _onClose = std::move(cb3);
    
}
void EventLoop::handleReadEvent(){
    uint64_t howmany = 0;
    int ret = read(_eventfd,&howmany,sizeof(howmany));
    if(ret != sizeof(howmany)){
        perror("read");
    }
}
void EventLoop::wakeup(){
    uint64_t one = 1;
    int ret = write(_eventfd,&one,sizeof(one)); 
    if(ret != sizeof(one)){
        perror("write");
    }
}
void EventLoop::runinLoop(Functor && f){
    {
        MutexLockGuard autolock(_mutex);
        _pendingFunctors.push_back(f);
    }
    wakeup();
}